package com.mazaiting.redeye.utils

import cn.jpush.im.android.api.model.UserInfo
import com.chad.library.adapter.base.entity.SectionEntity
import com.mazaiting.redeye.module.friend.FriendFragment
import java.util.regex.Pattern

/***
 *
 *
 *                                                    __----~~~~~~~~~~~------___
 *                                   .  .   ~~//====......          __--~ ~~
 *                   -.            \_|//     |||\\  ~~~~~~::::... /~
 *                ___-==_       _-~o~  \/    |||  \\            _/~~-
 *        __---~~~.==~||\=_    -_--~/_-~|-   |\\   \\        _/~
 *    _-~~     .=~    |  \\-_    '-~7  /-   /  ||    \      /
 *  .~       .~       |   \\ -_    /  /-   /   ||      \   /
 * /  ____  /         |     \\ ~-_/  /|- _/   .||       \ /
 * |~~    ~~|--~~~~--_ \     ~==-/   | \~--===~~        .\
 *          '         ~-|      /|    |-~\~~       __--~~
 *                      |-~~-_/ |    |   ~\_   _-~            /\
 *                           /  \     \__   \/~                \__
 *                       _--~ _/ | .-~~____--~-/                  ~~==.
 *                      ((->/~   '.|||' -_|    ~~-/ ,              . _||
 *                                 -_     ~\      ~~---l__i__i__i--~~_/
 *                                 _-~-__   ~)  \--______________--~~
 *                               //.-~~~-~_--~- |-------~~~~~~~~
 *                                      //.-~~~--\
 *                               神兽保佑
 *                              代码无BUG!
 * @author mazaiting
 * @date 2019-08-02
 * @description 联系人排序方法
 */
class SortComparator : Comparator<SectionEntity<UserInfo>> {

    companion object {

        /**
         * 字符列表
         */
        private val LIST_HEADER = arrayListOf("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S"
            ,"T","U","V","W","X","Y","Z")

        /**
         * 获取头部列表
         * @return 列表
         */
        private fun getHeaderList(): MutableList<SectionEntity<UserInfo>> {
            // 创建类别
            val list = mutableListOf<SectionEntity<UserInfo>>()
            // 迭代
            LIST_HEADER.forEach { list.add(object : SectionEntity<UserInfo>(true, it){}) }
            return list
        }

        /**
         * 获取用户信息列表
         */
        fun getUserInfoList(list: MutableList<UserInfo>): MutableList<SectionEntity<UserInfo>> {
            // 创建用户信息列表
            val userInfoList = mutableListOf<SectionEntity<UserInfo>>()
            // 遍历创建实体
            list.forEach { userInfoList.add(object : SectionEntity<UserInfo>(it) {}) }
            // 添加头部列表
            userInfoList.addAll(getHeaderList())
            // 根据汉字，拼音，英文，数字排序
            userInfoList.sortWith(SortComparator())
            // 创建临时列表
            val tmpList = arrayListOf<SectionEntity<UserInfo>>()
            // 添加所有用户信息列表
            tmpList.addAll(userInfoList)
            // 根据两个列表数据判断是否头部下方有数据，若没有，则移除
            for (i in 0 until tmpList.size - 1) {
                // 如果是头部，并且当前位置和下一位置相同，则说明头部下方无数据
                if (tmpList[i].isHeader && tmpList[i].isHeader == tmpList[i + 1].isHeader) {
                    // 移除当前位置
                    userInfoList.remove(tmpList[i])
                }
            }
            // 检测最后一条数据是否为头部
            if (tmpList[tmpList.size - 1].isHeader) {
                // 移除
                userInfoList.remove(tmpList[tmpList.size - 1])
            }
            return userInfoList
        }
    }

    /**
     * 判读是否是第一层的比较（递归调用中）
     */
    private var compareCallNum = 0

    override fun compare(entity1: SectionEntity<UserInfo>, entity2: SectionEntity<UserInfo>): Int {
        compareCallNum = 0

        val s1 = if (entity1.isHeader) {
            entity1.header
        } else {
            entity1.t.userName
        }

        val s2 = if (entity2.isHeader) {
            entity2.header
        } else {
            entity2.t.userName
        }
        return compareString(s1, s2)
    }

    /**
     * 只比较一个字符，递归调用较字符串
     * @param s1 字符串 1
     * @param s2 字符串 2
     * @return 0: 相等; 1: s1 > s2; -1: s1 < s2
     */
    private fun compareString(s1: String?, s2: String?): Int {
        compareCallNum++
        // 判断第一个字符，汉字最前，其次字母，然后是数字，若有其他符号，放在最后
        // 注意，由于递归调用，所以此处不能再使用trim了
        // 若存在长度为 0 的情况
        if (s1.isNullOrEmpty() && s2.isNullOrEmpty()) {
            return 0
        } else if (s1.isNullOrEmpty()) {
            return -1
        } else if (s2.isNullOrEmpty()) {
            return 1
        }

        // 获取第一个字符
        val firstStrA = s1.substring(0, 1)
        val firstStrB = s2.substring(0, 1)

        // 先从类型上来区分：汉字>字母>数字>其他符号，若类型不同，立即出比较的结果
        // 但是汉字与字母，由于存在首字母的分段，所以先不区分开
        var typeA = getFirstCharType(s1)
        var typeB = getFirstCharType(s2)
        // 判断
        if (typeA > typeB) {
            // 返回负值, 往前排
            return -1
        } else if (typeA < typeB) {
            return 1
        }

        // 类型相同，需要进行进一步的比较
        var compareResult: Int = 0
        // 不是字母与汉字
        if (typeA < 9 && typeB < 9) {
            // 比较
            compareResult = firstStrA.compareTo(firstStrB)
            return if (compareResult != 0) {
                // 若不同, 则比较出结果
                compareResult
            } else {
                // 若相同, 则递归
                compareString(s1.substring(1), s2.substring(1))
            }
        }

        // 字母或者汉字
        // 若是首字母，先用第一个字母或拼音进行比较
        // 否则，先判断字符类型
        val firstPinyinA = PinYinHelper.getFirstPingYin(s1)!!.substring(0, 1)
        val firstPinyinB = PinYinHelper.getFirstPingYin(s2)!!.substring(0, 1)

        if (compareCallNum == 1) {
            compareResult = firstPinyinA.compareTo(firstPinyinB)
            if (compareResult != 0) {
                return compareResult
            }
        }

        //若首字的第一个字母相同，或不是首字，判断原字符是汉字还是字母，汉字排在前面
        typeA = getFirstCharType2(s1)
        typeB = getFirstCharType2(s2)
        if (typeA > typeB) {
            return -1
        } else if (typeA < typeB) {
            return 1
        }

        //不是首字母，在字符类型之后判断，第一个字母或拼音进行比较
        if (compareCallNum != 1) {
            compareResult = firstPinyinA.compareTo(firstPinyinB)
            if (compareResult != 0) {
                return compareResult
            }
        }

        if (isLetter(s1) && isLetter(s2)) {
            //若是同一个字母，还要比较下大小写
            compareResult = firstStrA.compareTo(firstStrB)
            if (compareResult != 0) {
                return compareResult
            }
        }

        if (isHanzi(s1) && isHanzi(s2)) {
            //使用姓的拼音进行比较
//            compareResult = firstPinyinA.compareTo(firstPinyinB);
            compareResult = PinYinHelper.getFirstPingYin(s1)!!.compareTo(PinYinHelper.getFirstPingYin(s2)!!)
            if (compareResult != 0) {
                return compareResult
            }

            //若姓的拼音相同，比较汉字是否相同
            compareResult = firstStrA.compareTo(firstStrB)
            if (compareResult != 0) {
                return compareResult
            }
        }
        //若相同，则进行下一个字符的比较（递归调用）
        return compareString(s1.substring(1), s2.substring(1))
    }


    /**
     * 获取第一个字符类型
     * @param str 字符串
     */
    private fun getFirstCharType(str: String): Int {
        return when {
            isHanzi(str) -> 10
            isLetter(str) -> 10
            isNumber(str) -> 8
            else -> 0
        }
    }

    /**
     * 获取第一个字符类型 2
     * @param str 字符串
     */
    fun getFirstCharType2(str: String): Int {
        return when {
            isHanzi(str) -> 10
            isLetter(str) -> 9
            isNumber(str) -> 8
            else -> 0
        }
    }

    /**
     * 是否为汉字
     * @param str 字符串
     * @return true: 汉字; false: 非汉字
     */
    fun isHanzi(str: String): Boolean {
        val c = str[0]
        // 正则表达式，判断首字母是否是英文字母
        val pattern = Pattern.compile("[\\u4E00-\\u9FA5]+")
        return pattern.matcher(c + "").matches()
    }

    /**
     * 是否为字母
     * @param str 字符串
     * @return true: 字母; false: 不是字母
     */
    private fun isLetter(str: String): Boolean {
        val c = str[0]
        // 正则表达式，判断首字母是否是英文字母
        val pattern = Pattern.compile("^[A-Za-z]+$")
        return pattern.matcher(c + "").matches()
    }

    /**
     * 判断是否为数字
     * @param str 字符串
     * @return true: 数字; false: 非数字
     */
    private fun isNumber(str: String): Boolean {
        val c = str[0]
        // 正则表达式，判断首字母是否是英文字母
        val pattern = Pattern.compile("^[1-9]+$")
        return pattern.matcher(c + "").matches()
    }
}